home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / demos / stex3d.c < prev    next >
C/C++ Source or Header  |  1998-12-15  |  15KB  |  576 lines

  1. /* $Id: stex3d.c,v 3.1 1998/06/09 01:53:49 brianp Exp $ */
  2.  
  3. /*----------------------------- 
  4.  * stex3d.c GL example of the mesa 3d-texture extention to simulate procedural
  5.  *            texturing, it uses a perlin noise and turbulence functions.
  6.  * 
  7.  * Author:   Daniel Barrero
  8.  *           barrero@irit.fr
  9.  *           dbarrero@pegasus.uniandes.edu.co
  10.  *
  11.  * Converted to GLUT by brianp on 1/1/98
  12.  *
  13.  *      
  14.  * cc stex3d.c -o stex3d -lglut -lMesaGLU -lMesaGL -lX11 -lXext -lm 
  15.  *
  16.  *---------------------------- */
  17.  
  18. /*
  19.  * $Log: stex3d.c,v $
  20.  * Revision 3.1  1998/06/09 01:53:49  brianp
  21.  * main() should return an int
  22.  *
  23.  * Revision 3.0  1998/02/14 18:42:29  brianp
  24.  * initial rev
  25.  *
  26.  */
  27.  
  28.  
  29. #include <string.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <math.h>
  33. #include <GL/gl.h>
  34. #include <GL/glut.h>
  35. /* function declarations */
  36. #ifndef M_PI
  37. #define M_PI            3.14159265358979323846
  38. #endif
  39.  
  40. void init(void),
  41.      printHelp(void),
  42.      create3Dtexture(void),
  43.      setDefaults(void),
  44.      drawScene(void),
  45.      resize(int w, int h),
  46.      buildFigure(void),
  47.      initNoise(void);
  48. float turbulence(float point[3], float lofreq, float hifreq);
  49.  
  50. int isExtSupported(char *ext);
  51. void KeyHandler( unsigned char key, int x, int y );
  52. GLenum parseCmdLine(int argc, char **argv);
  53. float noise3(float vec[3]);
  54.       
  55. /* global variables */
  56. GLenum rgb, doubleBuffer, directRender, windType; /* visualization state*/
  57. float tex_width,tex_height,tex_depth;        /* texture volume dimensions  */
  58. unsigned char *voxels;                       /* texture data ptr */
  59. int angx,angy,angz;
  60. GLuint figure;
  61.  
  62. /*function definitions */
  63. int main(int argc, char **argv)
  64. {
  65.  
  66.  if (parseCmdLine(argc, argv) == GL_FALSE) {
  67.     exit(0);
  68.  }
  69.  
  70.  glutInitWindowPosition(0, 0);
  71.  glutInitWindowSize(400, 400);
  72.  windType = (rgb) ? GLUT_RGB : GLUT_INDEX;
  73.  windType |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
  74.  windType |= GLUT_DEPTH;
  75.  glutInitDisplayMode(windType);
  76.  
  77.  if (glutCreateWindow("stex3d") <= 0) {
  78.     exit(0);
  79.  }
  80.  /* init all */
  81.  init();
  82.  
  83.  glutReshapeFunc(resize);
  84.  glutKeyboardFunc(KeyHandler);
  85.  glutDisplayFunc(drawScene);
  86.  glutMainLoop();
  87.  return 0;
  88. }
  89.  
  90. void init()
  91.  /* init light */
  92.  GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  93.  GLfloat mat_shininess[] = { 25.0 };
  94.  GLfloat gray[] = { 0.6, 0.6, 0.6, 0.0 };
  95.  GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 };
  96.  GLfloat light_position[] = { 0.0, 1.0, 1.0, 0.0 };
  97.  
  98.  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  99.  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  100.  glLightfv(GL_LIGHT1, GL_POSITION, light_position);
  101.  glLightfv(GL_LIGHT1, GL_AMBIENT, gray);
  102.  glLightfv(GL_LIGHT1, GL_DIFFUSE, white);
  103.  glLightfv(GL_LIGHT1, GL_SPECULAR, white);
  104.  glColorMaterial(GL_FRONT, GL_DIFFUSE);
  105.  glEnable(GL_COLOR_MATERIAL);
  106.  glEnable(GL_LIGHTING);
  107.  glEnable(GL_LIGHT1);
  108.  
  109.  /* create torus for texturing */
  110.  figure=glGenLists(1); 
  111.  buildFigure();
  112. /* tkSolidTorus(figure,0.3,1.2);*/
  113.  
  114.  /* start the noise function variables */
  115.  initNoise();
  116.  
  117.  /* see if the texture 3d extention is supported */
  118.  if (!isExtSupported("GL_EXT_texture3D")) {
  119.    printf("Sorry this GL implementation (%s) does not support 3d texture extentions\n",
  120.     (char *)(glGetString(GL_RENDERER)));
  121. /*   tkQuit();*/
  122.  }
  123.  
  124.  /* if texture is supported then generate the texture */
  125.  create3Dtexture(); 
  126.  
  127.  glEnable(GL_TEXTURE_3D_EXT); 
  128.  /*
  129.  glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);
  130.  glEnable(GL_BLEND); 
  131.  */
  132.  glEnable(GL_DEPTH_TEST);
  133.  
  134.  glShadeModel(GL_FLAT);
  135.  glColor3f(0.6,0.7,0.8);
  136. }
  137.  
  138. void buildFigure(void)
  139. {   GLint i, j;
  140.     float theta1, phi1, theta2, phi2, rings, sides;
  141.     float v0[03], v1[3], v2[3], v3[3];
  142.     float t0[03], t1[3], t2[3], t3[3];
  143.     float n0[3], n1[3], n2[3], n3[3];
  144.     float innerRadius=0.4;
  145.     float outerRadius=0.8;
  146.     float scalFac;
  147.  
  148.     rings = 8;
  149.     sides = 10;
  150.     scalFac=1/(outerRadius*2);
  151.  
  152.     glNewList(figure, GL_COMPILE);
  153.     for (i = 0; i < rings; i++) {
  154.     theta1 = (float)i * 2.0 * M_PI / rings;
  155.     theta2 = (float)(i + 1) * 2.0 * M_PI / rings;
  156.     for (j = 0; j < sides; j++) {
  157.         phi1 = (float)j * 2.0 * M_PI / sides;
  158.         phi2 = (float)(j + 1) * 2.0 * M_PI / sides;
  159.  
  160.         v0[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi1));
  161.         v0[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi1));
  162.         v0[2] = innerRadius * sin(phi1);
  163.  
  164.         v1[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi1));
  165.         v1[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi1));
  166.         v1[2] = innerRadius * sin(phi1);
  167.         v2[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi2));
  168.         v2[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi2));
  169.         v2[2] = innerRadius * sin(phi2);
  170.  
  171.         v3[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi2));
  172.         v3[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi2));
  173.         v3[2] = innerRadius * sin(phi2);
  174.  
  175.         n0[0] = cos(theta1) * (cos(phi1));
  176.         n0[1] = -sin(theta1) * (cos(phi1));
  177.         n0[2] = sin(phi1);
  178.  
  179.         n1[0] = cos(theta2) * (cos(phi1));
  180.         n1[1] = -sin(theta2) * (cos(phi1));
  181.         n1[2] = sin(phi1);
  182.  
  183.         n2[0] = cos(theta2) * (cos(phi2));
  184.         n2[1] = -sin(theta2) * (cos(phi2));
  185.         n2[2] = sin(phi2);
  186.  
  187.         n3[0] = cos(theta1) * (cos(phi2));
  188.         n3[1] = -sin(theta1) * (cos(phi2));
  189.         n3[2] = sin(phi2);
  190.  
  191.         t0[0] = v0[0]*scalFac + 0.5;
  192.         t0[1] = v0[1]*scalFac + 0.5;
  193.         t0[2] = v0[2]*scalFac + 0.5;
  194.  
  195.         t1[0] = v1[0]*scalFac + 0.5;
  196.         t1[1] = v1[1]*scalFac + 0.5;
  197.         t1[2] = v1[2]*scalFac + 0.5;
  198.  
  199.         t2[0] = v2[0]*scalFac + 0.5;
  200.         t2[1] = v2[1]*scalFac + 0.5;
  201.         t2[2] = v2[2]*scalFac + 0.5;
  202.  
  203.         t3[0] = v3[0]*scalFac + 0.5;
  204.         t3[1] = v3[1]*scalFac + 0.5;
  205.         t3[2] = v3[2]*scalFac + 0.5;
  206.  
  207.         glBegin(GL_POLYGON);
  208.         glNormal3fv(n3); glTexCoord3fv(t3); glVertex3fv(v3);
  209.         glNormal3fv(n2); glTexCoord3fv(t2); glVertex3fv(v2);
  210.         glNormal3fv(n1); glTexCoord3fv(t1); glVertex3fv(v1);
  211.         glNormal3fv(n0); glTexCoord3fv(t0); glVertex3fv(v0);
  212.         glEnd();
  213.     }
  214.     }
  215.     glEndList();
  216. }
  217.  
  218. void create3Dtexture()
  219. {
  220.  int i,j,k;
  221.  unsigned char *vp;
  222.  float vec[3];
  223.  int tmp;
  224.  
  225.  printf("creating 3d textures...\n");
  226.  voxels = (unsigned char  *) malloc((4*tex_width*tex_height*tex_depth));
  227.  vp=voxels;
  228.  for (i=0;i<tex_width;i++){
  229.     vec[0]=i;
  230.     for (j=0;j<tex_height;j++) {
  231.       vec[1]=j;
  232.        for (k=0;k<tex_depth;k++) {
  233.        vec[2]=k;
  234.        tmp=(sin(k*i*j+turbulence(vec,0.01,1))+1)*127.5; 
  235.        *vp++=0;
  236.        *vp++=0;
  237.        *vp++=tmp; 
  238.        *vp++=tmp+128; 
  239.        }
  240.      }
  241.  }
  242.  
  243.  printf("setting up 3d texture...\n");
  244.  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  245.  glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  246.  glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  247.  glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S,     GL_REPEAT);
  248.  glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T,     GL_REPEAT);
  249.  glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_R_EXT, GL_REPEAT);
  250.  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, (GLint)GL_DECAL);
  251.  
  252.  glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, GL_RGBA,
  253.             tex_width, tex_height, tex_depth,
  254.             0, GL_RGBA, GL_UNSIGNED_BYTE, voxels);
  255.  
  256.  printf("finished setting up 3d texture image...\n");
  257. }
  258.  
  259. int isExtSupported(char *ext)
  260. {
  261.     /* routine to find whether a specified OpenGL extension is supported */
  262.  
  263.     char *c;
  264.     int len;
  265.     char *allext = (char *)(glGetString(GL_EXTENSIONS));
  266.  
  267.     len = strlen(ext);
  268.     if (len <= 0) return 0;
  269.  
  270.     c = allext;
  271.     while (c) {
  272.     if (!strncmp(c,ext,len)) return 1;
  273.     c = strchr(c+1,'G');
  274.     }
  275.     return 0;
  276. }
  277.  
  278. void printHelp()
  279. {
  280.   printf("\nUsage: stex3d  <cmd line options>\n"); 
  281.   printf(" cmd line options:\n");
  282.   printf("      -help   print this help!\n");
  283.   printf("      -rgb     RGBA mode. (Default)\n");
  284.   printf("      -ci     Color index mode.\n");
  285.   printf("      -sb     Single buffer mode. (Default)\n");
  286.   printf("      -db     Double buffer mode. \n");
  287.   printf("      -dr     Direct render mode.\n");
  288.   printf("      -ir     Indirect render mode. (Default)\n");
  289.   printf("      -wxxx   Width of the texture (Default=64)\n");
  290.   printf("      -hxxx   Height of the texture (Default=64)\n");
  291.   printf("      -dxxx   Depth of the texture (Default=64)\n");
  292.   printf(" Keyboard Options:\n");
  293.   printf("       1      Object Texture coordinates (Default)\n");
  294.   printf("       2      Eye Texture coordinates \n");
  295.   printf("       x      rotate around x clockwise\n");
  296.   printf("       X      rotate around x counter clockwise\n");
  297.   printf("       y      rotate around y clockwise\n");
  298.   printf("       Y      rotate around y counter clockwise\n");
  299.   printf("       z      rotate around z clockwise\n");
  300.   printf("       Z      rotate around z counter clockwise\n");
  301.   printf("       t      enable 3-D texuring (Default)\n");
  302.   printf("       T      disable 3-D texuring\n");
  303.   printf("       s      smooth shading \n");
  304.   printf("       S      flat shading (Default)\n");
  305. }
  306.  
  307. void setDefaults()
  308. {
  309.  /* visualization defaults */
  310.   rgb = GL_TRUE;
  311.   doubleBuffer = GL_FALSE;
  312.   directRender = GL_TRUE;
  313.   angx=130;
  314.   angy=30;
  315.   angz=0; 
  316.  /* texture values */
  317.  tex_width=64;
  318.  tex_height=64;
  319.  tex_depth=64;
  320. }
  321.  
  322. GLenum parseCmdLine(int argc, char **argv)
  323. {
  324.   GLint i;
  325.  
  326.   setDefaults();
  327.  
  328.   for (i = 1; i < argc; i++) {
  329.       if (strcmp(argv[i], "-ci") == 0) {
  330.       rgb = GL_FALSE;
  331.       } else if (strcmp(argv[i], "-rgb") == 0) {
  332.       rgb = GL_TRUE;
  333.       } else if (strcmp(argv[i], "-sb") == 0) {
  334.       doubleBuffer = GL_FALSE;
  335.       } else if (strcmp(argv[i], "-db") == 0) {
  336.       doubleBuffer = GL_TRUE;
  337.       } else if (strcmp(argv[i], "-dr") == 0) {
  338.       directRender = GL_TRUE;
  339.       } else if (strcmp(argv[i], "-ir") == 0) {
  340.       directRender = GL_FALSE;
  341.       } else if (strstr(argv[i], "-w") == 0) {
  342.       tex_width=atoi((argv[i])+2);
  343.       } else if (strstr(argv[i], "-h") == 0) {
  344.       tex_height=atoi((argv[i])+2);
  345.       } else if (strstr(argv[i], "-d") == 0) {
  346.       tex_depth=atoi((argv[i])+2);
  347.       } else if (strcmp(argv[i], "-help") == 0) {
  348.       printHelp();
  349.       return GL_FALSE;
  350.       } else {
  351.       printf("%s (Bad option).\n", argv[i]);
  352.       printHelp();
  353.       return GL_FALSE;
  354.       }
  355.   }
  356.  if(tex_width==0 || tex_height==0 || tex_depth==0) {
  357.    printf("%s (Bad option).\n", "size parameters can't be 0");
  358.    printHelp();
  359.    return GL_FALSE;
  360.  }
  361.   return GL_TRUE;
  362. }
  363.  
  364. void drawScene()
  365. {
  366.  /* clear background, z buffer etc */
  367.  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  368.  glPushMatrix();
  369.  glRotatef(angx,1.0,0.0,0.0);
  370.  glRotatef(angy,0.0,1.0,0.0);
  371.  glRotatef(angz,0.0,0.0,1.0);
  372.  
  373.  glCallList(figure);     
  374.  glPopMatrix();
  375.  glFlush();
  376.  if(doubleBuffer)
  377.     glutSwapBuffers();
  378.  ;
  379. }
  380.  
  381. void resize(int w, int h)
  382.  glViewport(0, 0, (GLint)w, (GLint)h);
  383.  glMatrixMode(GL_PROJECTION);
  384.  glLoadIdentity();
  385.  glOrtho(-2,2,-2,2,-5,10);
  386.  glMatrixMode(GL_MODELVIEW);
  387.  glLoadIdentity();
  388.  glTranslatef(0,0,-5);
  389. }
  390.  
  391. void cleanEverything(void)
  392. {
  393. /*  free(voxels); */
  394. }
  395.  
  396.  
  397. void KeyHandler( unsigned char key, int x, int y )
  398. {
  399.    switch(key) {
  400.       case 27:
  401.       case 'q':
  402.       case 'Q': /* quit game. */
  403.      cleanEverything();
  404.      exit(0);
  405.      break;
  406.       case 'x':
  407.      angx+=10;
  408.      break;
  409.       case 'X': 
  410.      angx-=10; 
  411.      break;
  412.       case 'y':
  413.      angy+=10;
  414.      break;
  415.       case 'Y': 
  416.      angy-=10; 
  417.      break;
  418.       case 'z':
  419.      angz+=10;
  420.      break;
  421.       case 'Z': 
  422.      angz-=10; 
  423.      break;
  424.       case 't':
  425.      glEnable(GL_TEXTURE_3D_EXT); 
  426.      break;
  427.       case 'T':
  428.      glDisable(GL_TEXTURE_3D_EXT);
  429.      break;
  430.       case 's':
  431.      glShadeModel(GL_SMOOTH);
  432.      break;
  433.       case 'S':
  434.      glShadeModel(GL_FLAT);
  435.      break;
  436.       case '1':
  437.      glDisable(GL_TEXTURE_GEN_S);
  438.      glDisable(GL_TEXTURE_GEN_T);
  439.      glDisable(GL_TEXTURE_GEN_R);
  440.      break;
  441.       case '2':
  442.      glEnable(GL_TEXTURE_GEN_S);
  443.      glEnable(GL_TEXTURE_GEN_T);
  444.      glEnable(GL_TEXTURE_GEN_R);
  445.      break;
  446.       default:
  447.      break;
  448.    }
  449.    glutPostRedisplay();
  450. }
  451.  
  452. /*--------------------------------------------------------------------
  453.  noise function over R3 - implemented by a pseudorandom tricubic spline 
  454.           EXCERPTED FROM SIGGRAPH 92, COURSE 23
  455.             PROCEDURAL MODELING
  456.                  Ken Perlin
  457.                New York University
  458. ----------------------------------------------------------------------*/
  459.  
  460.  
  461. #define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
  462. #define B 256
  463. static int p[B + B + 2];
  464. static float g[B + B + 2][3];
  465. #define setup(i,b0,b1,r0,r1) \
  466.     t = vec[i] + 10000.; \
  467.     b0 = ((int)t) & (B-1); \
  468.     b1 = (b0+1) & (B-1); \
  469.     r0 = t - (int)t; \
  470.     r1 = r0 - 1.;
  471.  
  472. float noise3(float vec[3])
  473. {
  474.     int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
  475.     float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
  476.     register int i, j;
  477.  
  478.     setup(0, bx0,bx1, rx0,rx1);
  479.     setup(1, by0,by1, ry0,ry1);
  480.     setup(2, bz0,bz1, rz0,rz1);
  481.  
  482.     i = p[ bx0 ];
  483.     j = p[ bx1 ];
  484.  
  485.     b00 = p[ i + by0 ];
  486.     b10 = p[ j + by0 ];
  487.     b01 = p[ i + by1 ];
  488.     b11 = p[ j + by1 ];
  489.  
  490. #define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
  491. #define surve(t) ( t * t * (3. - 2. * t) )
  492. #define lerp(t, a, b) ( a + t * (b - a) )
  493.  
  494.     sx = surve(rx0);
  495.     sy = surve(ry0);
  496.     sz = surve(rz0);
  497.  
  498.     q = g[ b00 + bz0 ] ; u = at(rx0,ry0,rz0);
  499.     q = g[ b10 + bz0 ] ; v = at(rx1,ry0,rz0);
  500.     a = lerp(sx, u, v);
  501.  
  502.     q = g[ b01 + bz0 ] ; u = at(rx0,ry1,rz0);
  503.     q = g[ b11 + bz0 ] ; v = at(rx1,ry1,rz0);
  504.     b = lerp(sx, u, v);
  505.  
  506.     c = lerp(sy, a, b);          /* interpolate in y at lo x */
  507.  
  508.     q = g[ b00 + bz1 ] ; u = at(rx0,ry0,rz1);
  509.     q = g[ b10 + bz1 ] ; v = at(rx1,ry0,rz1);
  510.     a = lerp(sx, u, v);
  511.  
  512.     q = g[ b01 + bz1 ] ; u = at(rx0,ry1,rz1);
  513.     q = g[ b11 + bz1 ] ; v = at(rx1,ry1,rz1);
  514.     b = lerp(sx, u, v);
  515.  
  516.     d = lerp(sy, a, b);          /* interpolate in y at hi x */
  517.  
  518.     return 1.5 * lerp(sz, c, d); /* interpolate in z */
  519. }
  520.  
  521. void initNoise()
  522. {
  523.     /*long random();*/
  524.     int i, j, k;
  525.     float v[3], s;
  526.  
  527. /* Create an array of random gradient vectors uniformly on the unit sphere */
  528.     /*srandom(1);*/
  529.     srand(1);
  530.     for (i = 0 ; i < B ; i++) {
  531.         do {                            /* Choose uniformly in a cube */                        for (j=0 ; j<3 ; j++)
  532.                 v[j] = (float)((rand() % (B + B)) - B) / B;
  533.             s = DOT(v,v);
  534.         } while (s > 1.0);              /* If not in sphere try again */                s = sqrt(s);
  535.         for (j = 0 ; j < 3 ; j++)       /* Else normalize */
  536.             g[i][j] = v[j] / s;
  537.     }
  538.  
  539. /* Create a pseudorandom permutation of [1..B] */
  540.     for (i = 0 ; i < B ; i++)
  541.         p[i] = i;
  542.     for (i = B ; i > 0 ; i -= 2) {
  543.         k = p[i];
  544.         p[i] = p[j = rand() % B];
  545.         p[j] = k;
  546.     }
  547.  
  548. /* Extend g and p arrays to allow for faster indexing */
  549.     for (i = 0 ; i < B + 2 ; i++) {
  550.         p[B + i] = p[i];
  551.         for (j = 0 ; j < 3 ; j++)
  552.             g[B + i][j] = g[i][j];
  553.     }
  554. }
  555.  
  556. float turbulence(float point[3], float lofreq, float hifreq)
  557. {
  558.     float freq, t, p[3];
  559.  
  560.     p[0] = point[0] + 123.456;
  561.     p[1] = point[1];
  562.     p[2] = point[2];
  563.  
  564.     t = 0;
  565.     for (freq = lofreq ; freq < hifreq ; freq *= 2.) {
  566.         t += fabs(noise3(p)) / freq;
  567.         p[0] *= 2.;
  568.         p[1] *= 2.;
  569.         p[2] *= 2.;
  570.     }
  571.     return t - 0.3; /* readjust to make mean value = 0.0 */
  572. }
  573.  
  574.